package cn.outmaneuver.outman.web.basic.config;
/**
 * Copyright 2023-2023 by DongYaoMing. All Rights Reserved.
 */

import cn.outmaneuver.outman.web.basic.constant.GlobalThreadConstants;
import cn.outmaneuver.outman.web.basic.exception.BusyException;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * GlobalThreadPoolConfigurtion
 * <p> </p>
 *
 * @author DongYaoMing
 * @version 1.0
 * @date 2023/10/18
 */
@Configuration
public class GlobalThreadPoolConfigurtion {

    /**
     * 基础线程池，用于公共代码中异步线程业务
     *
     * @return 基础线程池
     */
    @Bean(name = GlobalThreadConstants.BASE_THREAD_POOL)
    public ThreadPoolExecutor basePoolExecutor() {
        ThreadPoolExecutor tempExecutor = new ThreadPoolExecutor(4, 8, 100L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(200),
                new ThreadFactoryBuilder().setNameFormat("base-thread-pool-%d").build(),
                new ThreadPoolExecutor.CallerRunsPolicy());
        tempExecutor.allowCoreThreadTimeOut(true);
        return tempExecutor;
    }

    /**
     * 业务线程池，用于业务代码中异步线程业务
     *
     * @return 业务线程池
     */
    @Bean(name = GlobalThreadConstants.BUSINESS_THREAD_POOL)
    public ThreadPoolExecutor businessPoolExecutor() {
        ThreadPoolExecutor tempExecutor = new ThreadPoolExecutor(4, 8, 100L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(200),
                new ThreadFactoryBuilder().setNameFormat("business-thread-pool-%d").build(),
                new ThreadPoolExecutor.CallerRunsPolicy());
        tempExecutor.allowCoreThreadTimeOut(true);
        return tempExecutor;
    }

    /**
     * 自定义线程池，用于自定义代码中异步线程业务
     *
     * @return 自定义线程池
     */
    @Bean(name = GlobalThreadConstants.CUSTOM_THREAD_POOL)
    public ThreadPoolExecutor customPoolExecutor() {
        ThreadPoolExecutor tempExecutor = new ThreadPoolExecutor(2, 4, 100L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100),
                new ThreadFactoryBuilder().setNameFormat("custom-thread-pool-%d").build(),
                new CustomRejectedPolicy());
        tempExecutor.allowCoreThreadTimeOut(true);
        return tempExecutor;
    }

    /**
     * 日志线程池，用于异步日志记录时使用，如果日志积压过多（同时积压超过20000条），将会丢弃日志
     *
     * @return 日志线程池
     */
    @Bean(name = GlobalThreadConstants.LOG_THREAD_POOL)
    public ThreadPoolExecutor logPoolExecutor() {
        ThreadPoolExecutor tempExecutor = new ThreadPoolExecutor(4, 4, 60L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(20480),
                new ThreadFactoryBuilder().setNameFormat("log-thread-pool-%d").build(),
                new ThreadPoolExecutor.DiscardPolicy());
        tempExecutor.allowCoreThreadTimeOut(true);
        return tempExecutor;
    }


    public class CustomRejectedPolicy implements RejectedExecutionHandler {

        public CustomRejectedPolicy() {
        }

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            throw new BusyException();
        }
    }

}
